/*
 * Copyright 2011 Angel Sanadinov
 *
 * This file is part of VBox WMI.
 *
 * VBox WMI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VBox WMI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VBox WMI.  If not, see <http://www.gnu.org/licenses/>.
 */

package Beans.Responses.DataRetrievalComponents;

import com.sun.xml.ws.commons.virtualbox_3_2.IMediumFormat;
import com.sun.xml.ws.commons.virtualbox_3_2.ISystemProperties;
import com.sun.xml.ws.commons.virtualbox_3_2.IVirtualBox;
import java.io.Serializable;
import java.util.EnumMap;
import java.util.List;
import org.virtualbox_3_2.AudioDriverType;
import org.virtualbox_3_2.DeviceType;
import org.virtualbox_3_2.StorageBus;

/**
 * This class represents virtual system data, when retrieved from the system.
 *
 * @author Angel Sanadinov
 */
public class SystemVirtualBoxData extends DataRetrievalComponent
{
    //vbox data
    private String version;     //VBox version
    private int revision;       //VBox revision
    private String packageType; //VBox package type
    private String homeFolder;  //VBox home folder
    private String settingsFile;//VBox settings file location

    //guest constraints
    private int minRAMSize;     //minimum amount of RAM assignable to a guest (in MBs)
    private int maxRAMSize;     //maximum amount of RAM assignable to a guest (in MBs)
    private int minVRAMSize;    //minimum amount of VRAM assignable to a guest (in MBs)
    private int maxVRAMSize;    //maximum amount of VRAM assignable to a guest (in MBs)
    private int minCPUCount;    //minimum number of CPUs assignable to a guest
    private int maxCPUCount;    //maximum number of CPUs assignable to a guest
    private int maxMonitors;    //maximum number of monitors assignable to a guest
    private long maxVDISize;    //maximum size of a VDI image (in MBs)

    private int numberOfNetworkAdapters;//the number of network adapters per machine
    private int numberOfSerialPorts;    //the number of serial ports per machine
    private int numberOfParallelPorts;  //the number of parallel ports per machine

    private int maxBootPosition;//highest boot position

    //defaults
    private String defaultMachinesFolder;       //default machines folder
    private String defaultHardDisksFolder;      //default hard disks folder
    private String defaultHardDiskFormat;       //default hard disks format
    private AudioDriverType defaultAudioDriver; //default audio driver

    private IMediumFormat[] supportedMediumFormats; //supported medium formats

    //warnings
    private long freeDiskSpaceWarning;      //warn of low disk space if below ... MBs
    private int freeDiskSpaceWarningPercent;//warn of low disk space if below ... %
    private long freeDiskSpaceError;        //display error if disk space below ... MBs
    private int freeDiskSpaceErrorPercent;  //display error if disk space below ... %

    //misc
    private String VRDPAuthenticationLibrary;       //VRDP authentication library
    private String WebServiceAuthenticationLibrary; //Web Servie authentication library
    private int logHistoryCount;                    //log history count (for prev. versions)

    private EnumMap<StorageBus, StorageBusData> busConstraints; //storage bus constraints

    /**
     * Constructs a VirtualBox system data component, using data from the
     * IVirtualBox object.
     *
     * @param vbox the VirtualBox data object
     */
    public SystemVirtualBoxData(IVirtualBox vbox)
    {
        this.version = vbox.getVersion();
        this.revision = vbox.getRevision().intValue();
        this.packageType = vbox.getPackageType();
        this.homeFolder = vbox.getHomeFolder();
        this.settingsFile = vbox.getSettingsFilePath();

        ISystemProperties system = vbox.getSystemProperties();
        
        this.minRAMSize = system.getMinGuestRAM().intValue();
        this.maxRAMSize = system.getMaxGuestRAM().intValue();
        this.minVRAMSize = system.getMinGuestVRAM().intValue();
        this.maxVRAMSize = system.getMaxGuestVRAM().intValue();
        this.minCPUCount = system.getMinGuestCPUCount().intValue();
        this.maxCPUCount = system.getMaxGuestCPUCount().intValue();
        this.maxMonitors = system.getMaxGuestMonitors().intValue();
        //some data might be lost but it shouldn't be a problem as the size is in MB
        this.maxVDISize = system.getMaxVDISize().longValue();
        this.numberOfNetworkAdapters = system.getNetworkAdapterCount().intValue();
        this.numberOfSerialPorts = system.getSerialPortCount().intValue();
        this.numberOfParallelPorts = system.getParallelPortCount().intValue();
        this.maxBootPosition = system.getMaxBootPosition().intValue();
        this.defaultMachinesFolder = system.getDefaultMachineFolder();
        this.defaultHardDisksFolder = system.getDefaultHardDiskFolder();
        this.defaultHardDiskFormat = system.getDefaultHardDiskFormat();
        this.defaultAudioDriver = system.getDefaultAudioDriver();
        this.supportedMediumFormats = system.getMediumFormats().toArray(new IMediumFormat[system.getMediumFormats().size()]);
//        this.freeDiskSpaceWarning = system.getFreeDiskSpaceWarning().longValue(); //see maxVDISize
//        this.freeDiskSpaceWarningPercent = system.getFreeDiskSpacePercentWarning().intValue();
//        this.freeDiskSpaceError = system.getFreeDiskSpaceError().longValue(); //see maxVDISize
//        this.freeDiskSpaceErrorPercent = system.getFreeDiskSpacePercentError().intValue();
        this.VRDPAuthenticationLibrary = system.getRemoteDisplayAuthLibrary();
        this.WebServiceAuthenticationLibrary = system.getWebServiceAuthLibrary();
        this.logHistoryCount = system.getLogHistoryCount().intValue();
        
        EnumMap<StorageBus, StorageBusData> busData = new EnumMap<StorageBus, StorageBusData>(StorageBus.class);
        for(StorageBus storageBus : StorageBus.values())
        {
            List<DeviceType> deviceTypes = system.getDeviceTypesForStorageBus(storageBus);

            busData.put(storageBus, new StorageBusData(system.getMaxDevicesPerPortForStorageBus(storageBus).intValue(),
                                                       system.getMinPortCountForStorageBus(storageBus).intValue(),
                                                       system.getMaxPortCountForStorageBus(storageBus).intValue(),
                                                       system.getMaxInstancesOfStorageBus(storageBus).intValue(),
                                                       deviceTypes.toArray(new DeviceType[deviceTypes.size()])));
        }

        this.busConstraints = busData;
    }

    //<editor-fold defaultstate="collapsed" desc="Accessor Methods">
    /**
     * Retrieves the VirtualBox version.
     *
     * @return the VBox version
     */
    public String getVersion()
    {
        return version;
    }

    /**
     * Retrieves the VirtualBox revision.
     *
     * @return the VBox revision
     */
    public int getRevision()
    {
        return revision;
    }

    /**
     * Retrieves the VirtualBox package type.
     *
     * @return the VBox package type
     */
    public String getPackageType()
    {
        return packageType;
    }

    /**
     * Retrieves the VirtualBox home folder.
     *
     * @return the home folder
     */
    public String getHomeFolder()
    {
        return homeFolder;
    }

    /**
     * Retrieves the VirtualBox settings file location.
     *
     * @return the settings file location
     */
    public String getSettingsFile()
    {
        return settingsFile;
    }

    /**
     * Retrieves the minimum amount of RAM assignable to a guest.
     *
     * @return the minimum RAM size (in MBs)
     */
    public int getMinRAMSize()
    {
        return minRAMSize;
    }

    /**
     * Retrieves the maximum amount of RAM assignable to a guest.
     *
     * @return the maximum RAM size (in MBs)
     */
    public int getMaxRAMSize()
    {
        return maxRAMSize;
    }

    /**
     * Retrieves the minimum amount of VRAM assignable to a guest.
     *
     * @return the minimum VRAM size (in MBs)
     */
    public int getMinVRAMSize()
    {
        return minVRAMSize;
    }

    /**
     * Retrieves the maximum amount of RAM assignable to a guest.
     *
     * @return the maximum RAM size (in MBs)
     */
    public int getMaxVRAMSize()
    {
        return maxVRAMSize;
    }

    /**
     * Retrieves the minimum number of CPUs assignable to a guest.
     *
     * @return the minimum CPU number
     */
    public int getMinCPUCount()
    {
        return minCPUCount;
    }

    /**
     * Retrieves the maximum number of CPUs assignable to a guest.
     *
     * @return the maximum CPU number
     */
    public int getMaxCPUCount()
    {
        return maxCPUCount;
    }

    /**
     * Retrieves the maximum number of monitors assignable to a guest.
     *
     * @return the maximum monitor number
     */
    public int getMaxMonitors()
    {
        return maxMonitors;
    }

    /**
     * Retrieves the maximum size of a VDI image.
     *
     * @return the maximum VDI image size (in MBs)
     */
    public long getMaxVDISize()
    {
        return maxVDISize;
    }

    /**
     * Retrieves the number of network adapters for a virtual machine.
     *
     * @return the network adapters number
     */
    public int getNumberOfNetworkAdapters()
    {
        return numberOfNetworkAdapters;
    }

    /**
     * Retrieves the number of serial port for a virtual machine.
     *
     * @return the number of serial ports
     */
    public int getNumberOfSerialPorts()
    {
        return numberOfSerialPorts;
    }

    /**
     * Retrieves the number of parallel port for a virtual machine.
     *
     * @return the number of parallel ports
     */
    public int getNumberOfParallelPorts()
    {
        return numberOfParallelPorts;
    }

    /**
     * Retrieves the highest boot position available.
     *
     * @return the highest boot position
     */
    public int getMaxBootPosition()
    {
        return maxBootPosition;
    }

    /**
     * Retrieves the default machines folder on the host.
     *
     * @return the default machines folder
     */
    public String getDefaultMachinesFolder()
    {
        return defaultMachinesFolder;
    }

    /**
     * Retrieves the default hard disks folder on the host.
     *
     * @return the default hard disks folder
     */
    public String getDefaultHardDisksFolder()
    {
        return defaultHardDisksFolder;
    }

    /**
     * Retrieves the default hard disks format.
     *
     * @return the default hard disks format
     */
    public String getDefaultHardDiskFormat()
    {
        return defaultHardDiskFormat;
    }

    /**
     * Retrieves the default audio driver.
     *
     * @return the default audio driver
     */
    public AudioDriverType getDefaultAudioDriver()
    {
        return defaultAudioDriver;
    }

    /**
     * Retrieves the supported medium formats.
     *
     * @return an array of supported medium formats
     */
    public IMediumFormat[] getSupportedMediumFormats()
    {
        return supportedMediumFormats;
    }

    /**
     * Retrieves the free disk space warning threshold.
     *
     * @return the threshold (in MBs)
     */
    public long getFreeDiskSpaceWarning()
    {
        return freeDiskSpaceWarning;
    }

    /**
     * Retrieves the free disk space warning threshold.
     *
     * @return the threshold (in percents)
     */
    public int getFreeDiskSpaceWarningPercent()
    {
        return freeDiskSpaceWarningPercent;
    }

    /**
     * Retrieves the free disk space error threshold.
     *
     * @return the threshold (in MBs)
     */
    public long getFreeDiskSpaceError()
    {
        return freeDiskSpaceError;
    }

    /**
     * Retrieves the free disk space error threshold.
     *
     * @return the threshold (in percents)
     */
    public int getFreeDiskSpaceErrorPercent()
    {
        return freeDiskSpaceErrorPercent;
    }

    /**
     * Retrieves the VRDP authentication library.
     *
     * @return the authentication library
     */
    public String getVRDPAuthenticationLibrary()
    {
        return VRDPAuthenticationLibrary;
    }

    /**
     * Retrieves the Web Service authentication library.
     *
     * @return the authentication library
     */
    public String getWebServiceAuthenticationLibrary()
    {
        return WebServiceAuthenticationLibrary;
    }

    /**
     * Retrieves the number of old release log files to keep.
     *
     * @return the log history count
     */
    public int getLogHistoryCount()
    {
        return logHistoryCount;
    }

    /**
     * Retrieves the constraints for each storage bus.
     *
     * @return a map of storage bus constraints
     */
    public EnumMap<StorageBus, StorageBusData> getBusConstraints()
    {
        return busConstraints;
    }
    //</editor-fold>

    /**
     * Checks if the storage bus data is valid.
     *
     * @return <code>true</code> if the data is valid or <code>false</code> if it is not
     */
    private boolean areBusConstraintsValid()
    {
        if(busConstraints != null && !busConstraints.isEmpty())
        {
            for(StorageBusData data : busConstraints.values())
            {
                if(data == null)
                    return false;
                else
                    ;
            }

            return true;
        }
        else
            return false;
    }

    @Override
    public boolean isValid()
    {
        if(areBusConstraintsValid() && supportedMediumFormats != null && defaultAudioDriver != null
                && version != null)
            return true;
        else
            return false;
    }

    /**
     * This class represents storage bus data.
     */
    public class StorageBusData implements Serializable
    {
        private int maxDevicesPerPort;          //maximum devices per port
        private int minPortCount;               //minimum usable port
        private int maxPortCount;               //maximum usable port
        private int maxNumberOfBusInstances;    //maximum number of bus instances per vm
        private DeviceType[] supportedDevices;  //types of devices supported by the bus

        /**
         * Constructs a storage bus data object, using the specified data.
         *
         * @param maxDevicesPerPort the maximum devices per port
         * @param minPortCount the lowest usable port
         * @param maxPortCount the highest usable port
         * @param maxNumberOfBusInstances the maximum number of bus instances per machine
         * @param supportedDevices the types of devices supported by the bus
         */
        public StorageBusData(int maxDevicesPerPort, int minPortCount, int maxPortCount,
                              int maxNumberOfBusInstances, DeviceType[] supportedDevices)
        {
            this.maxDevicesPerPort = maxDevicesPerPort;
            this.minPortCount = minPortCount;
            this.maxPortCount = maxPortCount;
            this.maxNumberOfBusInstances = maxNumberOfBusInstances;
            this.supportedDevices = supportedDevices;
        }

        /**
         * Retrieves the maximum devices per port.
         *
         * @return the max devices per port
         */
        public int getMaxDevicesPerPort()
        {
            return maxDevicesPerPort;
        }

        /**
         * Retrieves the lowest usable port.
         *
         * @return the port
         */
        public int getMinPortCount()
        {
            return minPortCount;
        }

        /**
         * Retrieves the highest usable port.
         *
         * @return the port
         */
        public int getMaxPortCount()
        {
            return maxPortCount;
        }

        /**
         * Retrieves the maximum number of bus instances per virtual machine.
         *
         * @return the maximum number of bus instances
         */
        public int getMaxNumberOfBusInstances()
        {
            return maxNumberOfBusInstances;
        }

        /**
         * Retrieves the device types supported by the bus.
         *
         * @return an array with supported device types
         */
        public DeviceType[] getSupportedDevices()
        {
            return supportedDevices;
        }
    }
}
